Previous Book Contents Book Index Next

Inside Macintosh: Overview /
Chapter 5 - Drawing


Drawing Text

In addition to the many routines it provides for defining and drawing both simple and complex graphic elements, QuickDraw also provides support for drawing text. You can use QuickDraw to draw characters, words, or other textual elements at any desired size and in any available font. It might seem odd that QuickDraw handles these operations, until you realize that text, like graphics, permeates the Macintosh user interface. Windows, menus, and some controls (for instance, buttons) have titles, which are essential to the user's understanding and manipulation of the application. As a result, it makes sense to treat text fundamentally as a graphic object and to assign basic text-drawing responsibilities to QuickDraw, which manages all graphics within the Macintosh system software.

Although QuickDraw is ultimately responsible for drawing text on the screen, you might need to use other Toolbox managers for other text-handling needs. For example, if you want the user to be able to input and edit some small amount of text, you can use TextEdit. TextEdit provides basic text-editing capabilities, such as cutting, copying, pasting, and entering words and characters. TextEdit calls QuickDraw to display the editable text. Similarly, if your application allows the user to display text in a variety of fonts, you might need to use the Font Manager. The Font Manager supports QuickDraw by providing the character bitmaps it needs to draw text in a specified font, size, and style. For a complete description of TextEdit and the Font Manager, see Inside Macintosh: Text.

The Venn Diagrammer application has very minimal text-handling requirements. It does not support any text entry or editing by the user. Instead, it obtains all the text it needs from resources stored in its resource fork. As a result, the Venn Diagrammer application can use basic QuickDraw text-drawing routines to display its text. For example, the Venn Diagrammer application draws the message in a window's status area by calling the application-defined routine DoStatusMesg, defined in Listing 5-9.

Listing 5-9 Retrieving a status message from a resource

PROCEDURE DoStatusMesg (myWindow: WindowPtr; myMessageID: Integer);
   VAR
      myText:     Str255;
BEGIN
   GetIndString(myText, rVennD, myMessageID);
   DoStatusText(myWindow, myText);
END;
As you can see, the DoStatusMesg routine takes two parameters, a window pointer specifying the window whose status area is to be filled in and an integer specifying the index into an 'STR#' resource. Then DoStatusMesg retrieves the appropriate message text and calls the application-defined procedure DoStatusText to print the message in the window.

Venn Diagrammer calls DoStatusMesg whenever it needs to display a message in the status area. For instance, when the user wants to determine if a syllogism is valid or not, Venn Diagrammer checks the syllogism's validity and then executes the code in
Listing 5-10.

Listing 5-10 Informing the user of an argument's validity or invalidity

IF valid THEN
   BEGIN
      IF gShowNames THEN      {show names of valid syllogisms?}
         BEGIN
            GetIndString(myMesg, rVennD, eArgIsValid);
            DoGetName(myWindow, myName);
            myMesg := concat(myMesg, ' (', myName, ')');
            DoStatusText(myWindow, myMesg);
         END
      ELSE
         DoStatusMesg(myWindow, eArgIsValid);
   END
ELSE
   DoStatusMesg(myWindow, eArgNotValid);
This code fragment illustrates why the Venn Diagrammer application defines two different routines, DoStatusMesg and DoStatusText. The first, DoStatusMesg, retrieves the desired message text from a resource and calls the second, DoStatusText, to display it on the screen. The application also calls DoStatusText at other times, for instance, when it needs to add something to the resource-based message string. In the example shown in Listing 5-10, the application needs to get the name of the valid syllogism, if the user has indicated that this should be done.

The DoStatusText procedure is defined in Listing 5-11. Its job is to display the text passed as a parameter in the status area of the specified window.

Listing 5-11 Displaying a status message

PROCEDURE DoStatusText (myWindow: WindowPtr; myText: Str255);
   VAR
      myRect:     Rect;
      origSize:   Integer;
      origFont:   Integer;
      myHandle:   MyDocRecHnd;
   CONST
      kSlop = 4;
      kSize = 9;
      kFont = applFont;
BEGIN
   IF myWindow <> NIL THEN
      BEGIN
         SetPort(myWindow);
         origSize := myWindow^.txSize;    {remember original size and font}
         origFont := myWindow^.txFont;
         TextSize(kSize);                 {set desired size and font}
         TextFont(kFont);

         SetRect(myRect, kToolWd * kNumTools, 0,
                            myWindow^.portRect.right, kToolHt);
         EraseRect(myRect);
         IF length(myText) > 0 THEN
            BEGIN
               MoveTo(myRect.left + kSlop, myRect.bottom - kSlop);
               DrawString(myText);
            END;

         TextSize(origSize);              {restore original size and font}
         TextFont(origFont);

         {Remember the last message printed in this window.}
         myHandle := MyDocRecHnd(GetWRefCon(myWindow));
         myHandle^^.statusText := myText;
      END;
END;
The DoStatusText procedure first remembers the graphics port's existing font and size, so that it can change and then later restore those values. Then DoStatusText sets the desired font and size of the status message by calling the QuickDraw routines TextFont and TextSize. You should always use these routines--instead of changing the fields of the grafPort record--whenever you want to change a graphics port's font and size.

IMPORTANT
Although you should never change the fields of a graphics port directly, you sometimes need to read those fields directly. In Listing 5-11, the original font and size are determined by reading the appropriate fields (txFont and txSize) of the graphics port record. This is necessary because QuickDraw doesn't provide routines to read that information from a graphics port record.
Once it's set the desired font and size, the DoStatusText procedure calls SetRect to define the rectangle into which the text is to be drawn. Then, DoStatusText erases that rectangle by calling EraseRect. If the string to be displayed consists of at least one character, DoStatusText moves to the appropriate spot in the status area and calls the QuickDraw routine DrawString, which draws the specified string at the current drawing location in the window.

Finally, DoStatusText restores the graphics port's original font and size, and then copies the string just drawn into the statusText field of the window's document record. The Venn Diagrammer application needs to remember each window's latest status message so that it can redraw the message whenever necessary (for example, if the message is covered up by another window and then later revealed).

Venn Diagrammer uses similar techniques for all other text drawing it requires. Remember that this application supports only static text (that is, text that cannot be edited) stored in the application's resource fork. To allow the user to enter and edit some text, you need to use more powerful text-handling tools. See Inside Macintosh: Text for information about using system software services like the Font Manager and TextEdit to handle editable text. See Inside Macintosh: Files for information on storing text and other data in files. Finally, see the chapter "Dialog Manager" in Inside Macintosh: Macintosh Toolbox Essentials for information on handling text entry and editing in a dialog box.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
9 JUL 1996